package com.mfp.java.testYou.db.mock;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import com.mfp.java.testYou.db.model.Answer;
import com.mfp.java.testYou.db.model.CompletedTest;
import com.mfp.java.testYou.db.model.Question;
import com.mfp.java.testYou.db.model.Test;
import com.mfp.java.testYou.db.model.User;
import com.mfp.java.testYou.db.model.UserRole;

class UserWithPass extends User implements Serializable {
	private static final long serialVersionUID = -4258554324959853561L;
	private CharSequence pass;

	public final CharSequence getPass() {
		return pass;
	}

	public final void setPass(CharSequence pass) {
		this.pass = pass;
	}

}

public class MockPersisterObject implements Serializable {

	private static final Logger log = Logger.getLogger(MockPersisterObject.class);

	private static final long serialVersionUID = -4601613916570078114L;

	private List<UserWithPass> userList;
	private List<Question> questionsList;
	private List<Test> testsList;
	private List<CompletedTest> compTests;

	private static synchronized int generateUID() {
		long l = new Date().getTime();
		long l2 = l % (Integer.MAX_VALUE - 1);
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			log.error("ID generation interrupted!");
		}
		return (int) l2;
	}

	private void initUsers() {
		userList = new LinkedList<UserWithPass>();

		User admin = new User();
		admin.setLang("en");
		admin.setUserName("admin");
		admin.setRole(UserRole.ADMIN);
		addUser(admin, "");
		log.info("Added 'admin' user");

		User student = new User();
		student.setLang("en");
		student.setUserName("student");
		student.setRole(UserRole.USER);
		addUser(student, "");
		log.info("Added 'student' user");
	}

	private void initQuestions() {
		questionsList = new LinkedList<Question>();
	}

	private void initTests() {
		testsList = new LinkedList<Test>();
	}

	private void initCTests() {
		compTests = new LinkedList<CompletedTest>();
	}

	public MockPersisterObject() {
		initUsers();
		initQuestions();
		initTests();
		initCTests();
	}

	public User addUser(User user, CharSequence pass) {
		user.setId(generateUID());

		UserWithPass user2 = new UserWithPass();
		user2.setId(user.getId());
		user2.setLang(user.getLang());
		user2.setRole(user.getRole());
		user2.setUserName(user.getUserName());
		user2.setPass(pass);

		userList.add(user2);
		return user;
	}

	public List<User> getAllUsers() {
		List<User> list = new LinkedList<User>();
		for (UserWithPass uwp : userList) {
			list.add(uwp);
		}
		return list;
	}

	public User editUser(User newUserData, CharSequence pass, int userId) throws SQLException {
		for (UserWithPass uwp : userList) {
			if (uwp.getId() == userId) {
				uwp.setLang(newUserData.getLang());
				uwp.setRole(newUserData.getRole());
				if (pass != null) {
					uwp.setPass(pass);
				}
				return uwp;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public void deleteUser(int userId) {
		for (UserWithPass uwp : userList) {
			if (uwp.getId() == userId) {
				userList.remove(uwp);
				return;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public Question addQuestion(Question q) {
		q.setId(MockPersisterObject.generateUID());
		for (Answer a : q.getAnswers()) {
			a.setId(MockPersisterObject.generateUID());
		}
		questionsList.add(q);
		return q;
	}

	public void deleteQuestion(int qId) {
		for (Question q : getAllQuestions()) {
			if (q.getId() == qId) {
				questionsList.remove(q);
				return;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public List<Question> getAllQuestions() {
		return questionsList;
	}

	public Test addTest(Test t) {
		t.setId(MockPersisterObject.generateUID());
		testsList.add(t);
		return t;
	}

	public List<Test> getAllTests() {
		return testsList;
	}

	public Question editQuestion(Question question, Integer qIdInt) {
		for (Question q : questionsList) {
			if (q.getId() == qIdInt) {
				q.setAnswers(question.getAnswers());
				q.setHint(question.getHint());
				q.setText(question.getText());

				for (Answer a : q.getAnswers()) {
					a.setId(MockPersisterObject.generateUID());
				}

				return q;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public Test editTestDetails(Test test, Integer testIdInt) {
		for (Test t : testsList) {
			if (t.getId() == testIdInt) {
				t.setTitle(test.getTitle());
				t.setAllowHints(test.isAllowHints());
				t.setFinalTest(test.isFinalTest());
				return t;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public void deleteTest(Integer testIdInt) {
		for (Test t : testsList) {
			if (t.getId() == testIdInt) {
				testsList.remove(t);
				return;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public Question getQuestion(Integer qId) {
		for (Question q : getAllQuestions()) {
			if (q.getId() == qId) {
				return q;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public Test getTest(Integer testId) {
		for (Test t : getAllTests()) {
			if (t.getId() == testId) {
				return t;
			}
		}
		throw new IllegalArgumentException("Could not find id");
	}

	public void addQuestionToTest(Integer testId, Integer questionId) {
		Question q = this.getQuestion(questionId);
		Test t = this.getTest(testId);
		t.getQuestions().add(q);
	}

	public void deleteQuestionFromTest(Integer testId, Integer questionId) {
		Question q = this.getQuestion(questionId);
		Test t = this.getTest(testId);
		t.getQuestions().remove(q);
	}

	public void addCompletedTest(CompletedTest ct) {
		compTests.add(ct);
	}

	public List<CompletedTest> getAllResults() {
		return compTests;
	}
}
